// * 柯里化是一种函数的转换，它是指将一个函数从可调用的 f(a, b, c) 转换为可调用的 f(a)(b)(c)。
// * 柯里化不会调用函数。它只是对函数进行转换。

// 例子：
function curry(f) {
	return function (a) {
		return function (b) {
			return f(a, b)
		}
	}
}

function sum(a, b) {
	return a + b
}

let curriedSum = curry(sum)

console.log(curriedSum(1)(2)) // 3

// ****************************************************************************************************************

// * 高级柯里化实现
function curry(func) {
	// func === sums
	// curried === curriedSums

	return function curried(...args) {
		// func.length === 3

		if (args.length >= func.length) {
			return func.apply(this, args)
		} else {
			return function (...args2) {
				return curried.apply(this, args.concat(args2))
			}
		}
	}
}

function sums(a, b, c) {
	return a + b + c
}

let curriedSums = curry(sums)

console.log(curriedSums(1, 2, 3)) // 6 常规调用
console.log(curriedSums(1, 2)(3)) // 6 对第一个参数的柯里化
console.log(curriedSums(1)(2)(3)) // 6 全柯里化

// ****************************************************************************************************************

// * 只允许确定参数长度的函数:
// * 柯里化要求函数具有固定数量的参数。
// * 使用 rest 参数的函数，例如 f(...args)，不能以这种方式进行柯里化。
